﻿using HproseRpcTester.Utils;
using Newtonsoft.Json;
using System;

namespace HproseRpcTester.Service
{
    public abstract class RPCBase
    {
        public virtual string Success() => RPCMessage.Success().ToJson();

        /// <summary>
        /// 常用：把整个RPCmessage 转化为string: 且RPCmessage 为成功
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public virtual string Success<T>(T data, string msg)
        {
            return RPCMessage.Success<T>(data, msg).ToJson();
        }

        /// <summary>
        /// 常用：把整个RPCmessage 转化为string: 且RPCmessage 为失败
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public virtual string Error<T>(T data, string msg)
        {
            return RPCMessage.Error<T>(data, msg).ToJson();
        }


        public virtual string Success<T>(T data) => RPCMessage.Success(data).ToJson();

        public virtual string Error() => RPCMessage.Error().ToJson();

        public virtual string Error(Exception e) => RPCMessage.Error($"{e.Message}\n{e.StackTrace}").ToJson();

        public virtual string Error(RPCMessageCode code) => RPCMessage.Error(code).ToJson();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public virtual string Error(string msg) => RPCMessage.Error(msg).ToJson();

        public virtual string Error(RPCMessageCode code, string msg) => RPCMessage.Error(code, msg).ToJson();
    }

    /// <summary>
    /// Data.toData<T> 来获取数据.
    /// 服务端，结果传递
    /// </summary>
    public class RPCMessage
    {
        //[JsonProperty("c")]
        public RPCMessageCode Code { get; set; } = RPCMessageCode.Success;

        //[JsonProperty("d")]
        public string Data { get; set; }

        //[JsonProperty("m")]
        public string Message { get; set; }

        public static RPCMessage Success()
        {
            return new RPCMessage()
            {
                Data = "",
                Message = "Success"
            };
        }

        public static RPCMessage TimeOut
        {
            get
            {
                return new RPCMessage()
                {
                    Code = RPCMessageCode.Timeout,
                    Data = "",
                    Message = "TimeOut"
                };
            }
        }

        public static RPCMessage Success<T>(T data)
        {
            return new RPCMessage()
            {
                Data = data.ToJson(),
                Message = "Success"
            };
        }

        /// <summary>
        /// 成功msg初始化。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="strMsg"></param>
        /// <returns></returns>
        public static RPCMessage Success<T>(T data, string strMsg)
        {
            return new RPCMessage()
            {
                Code = RPCMessageCode.Success,
                Data = data?.ToJson(),
                Message = strMsg
            };
        }


        public static RPCMessage Error()
        {
            return new RPCMessage()
            {
                Code = RPCMessageCode.Error,
                Data = "",
                Message = "Error"
            };
        }

        public static RPCMessage Error(RPCMessageCode code)
        {
            return new RPCMessage()
            {
                Code = code,
                Data = "",
                Message = "Error"
            };
        }

        public static RPCMessage Error(string msg)
        {
            return new RPCMessage()
            {
                Code = RPCMessageCode.Error,
                Data = "",
                Message = msg
            };
        }

        /// <summary>
        /// 失败msg初始化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="strMsg"></param>
        /// <returns></returns>
        public static RPCMessage Error<T>(T data, string strMsg)
        {
            return new RPCMessage()
            {
                Code = RPCMessageCode.Error,
                Data = data.ToJson(),
                Message = strMsg
            };
        }      

        public static RPCMessage Error(RPCMessageCode code, string msg)
        {
            return new RPCMessage()
            {
                Code = code,
                Data = "",
                Message = msg
            };
        }

        public RPCMessage getInstance()
        {
            throw new NotImplementedException();
        }
    }

    public enum RPCMessageCode
    {
        Timeout = -99,
        Error = -1,
        Success = 0,

        #region PCR
        PCR_Status = 100,
        PCR_Progress = 101,
        PCR_Error = 102,
        #endregion

        #region 其他枚举请自觉按照功能区分块
        UnDefined = 999999
        #endregion
    }

    public static class RPCMessageExtension
    {
        public static RPCMessage ToRPCMessage(this string src) => JsonConvert.DeserializeObject<RPCMessage>(src);
        public static RPCParam ToRPCParam(this string src) => JsonConvert.DeserializeObject<RPCParam>(src);
    }

    /// <summary>
    /// PRC 客户端调用时，传递参数
    /// 全部序列化：RPCParam.ToJson
    /// </summary>
    public class RPCParam
    {
        [JsonProperty("c")]
        public UInt32 CmdCode { get; set; }

        [JsonProperty("d")]
        public string Data { get; set; }

        [JsonProperty("t")]
        public uint TimeOut { get; set; }

        public static RPCParam getNewParam<T>(UInt32 inCmdCode, T data, uint timeOut)
        {
            return new RPCParam()
            {
                CmdCode = inCmdCode,
                Data = data?.ToJson(),
                TimeOut = timeOut
            };
        }
    }
}
